package com.code.common.utils.template;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * @author lyf
 * @date 2020-08-17 2:17 下午
 */
@Data
@Slf4j
public abstract class RetryTemplate<T> {

    private static final int DEFAULT_RETRY_TIME = 1;

    private int retryTime = DEFAULT_RETRY_TIME;

    // 重试的睡眠时间
    private int sleepTime = 0;

    // final不可被子类重写
    public final RetryTemplate<T> setSleepTime(int sleepTime) {
        if(sleepTime < 0) {
            throw new IllegalArgumentException("sleepTime should equal or bigger than 0");
        }

        this.sleepTime = sleepTime;
        return this;
    }

    // final不可被子类重写
    public final RetryTemplate<T> setRetryTime(int retryTime) {
        if (retryTime <= 0) {
            throw new IllegalArgumentException("retryTime should bigger than 0");
        }

        this.retryTime = retryTime;
        return this;
    }

    /**
     * 重试的业务执行代码
     * 失败时请抛出一个异常
     *
     * @return
     */
    protected abstract T process() throws Exception;

    // protected 修饰的方法，只有继承的类才能被看到
    public T execute() {
        for (int i = 1; i <= retryTime; i++) {
            try {
                return process();
            } catch (Exception e) {
                log.error("重试业务失败,重试次数: {}, 异常信息:{}", i, e);
                try {
                    TimeUnit.MILLISECONDS.sleep(sleepTime);
                } catch (InterruptedException interruptedException) {
                    log.warn("线程睡眠异常: {}", interruptedException);
                    Thread.currentThread().interrupt();
                    return null;
                }
            }
        }
        return null;
    }
}
